ASSERT_BOOLEAN_EQ = 1;
ASSERT_BYTE_EQ = 2;
ASSERT_CHAR_EQ = 4;
ASSERT_DOUBLE_EQ = 8;
ASSERT_INT_EQ = 16;
ASSERT_OBJECT_EQ = 32;
ASSERT_STRING_EQ = 64;
ASSERT_FALSE = 128;
ASSERT_NOT_NULL = 256;
ASSERT_NULL = 512;
ASSERT_NOT_SAME = 1024;
ASSERT_SAME = 2048;
ASSERT_FAIL = 4096;
ASSERT_TRUE = 8192;

ASSERT_SET_BOOL = ASSERT_BOOLEAN_EQ | ASSERT_FALSE | ASSERT_TRUE;
ASSERT_SET_STRING = ASSERT_STRING_EQ | ASSERT_NOT_NULL | ASSERT_NULL;
ASSERT_SET_VALUE = ASSERT_BOOLEAN_EQ | ASSERT_BYTE_EQ | ASSERT_CHAR_EQ | ASSERT_INT_EQ |
                   ASSERT_STRING_EQ | ASSERT_NOT_NULL | ASSERT_NULL | ASSERT_DOUBLE_EQ;

// Assert SAME, NOT_SAME and OBJECT are all probably going to be handled at a much, much later date.

Assertion = domplate(TestFireObject, {


    targetObject: null,
    htmlFinder: null,
    parent: null,
    deletable: 1,
    args: {},



    doInit: function( parent, displayValue, args )
    {
        this.parent = parent;
        this.displayValue = displayValue;
        this.init.apply(this, arguments);
        this.args = args ? args : {};
        this.upDownEnabled = true;

    },

    isUpAvailable : function()
    {
        return this._isUpAvailable(this.parent.tasks);

    },

    isDownAvailable : function()
    {
        return this._isDownAvailable(this.parent.tasks);
    },

    moveDown : function()
    {
        return this._moveDown(this.parent.tasks);
    },

    moveUp : function()
    {
        return this._moveUp(this.parent.tasks);
    },

/**
 * Get all displayable children and their names in an array of objects. The returned values will be displayed
 * in the order returned.
 * @return An array containing objects of the form: {name: 'name', object: this[name]} .
 */
    getChildrenToDisplay: function()
    {
        var ary = new Array();
        if ( this.required )
        {
            for ( var name in this.required )
            {

            }
        }
        ary.push({name: "required" , object: this.required});
        ary.push({name: "optional" , object: this.optional});
        if ( this.targetObject )
        {
            ary.push({name: "Target Object" , object: this.targetObject});
        }

        return ary;
    },


/**
 * A simple default.
 * @return if this has displayable children or not.
 */
    getHasChildren: function()
    {
        return this.getChildrenToDisplay().length != 0;
    },

    open : function(element)
    {
        var childElement = this.getFirstChildElement(element);
        var expected = childElement.getAttribute('expected');
        var message = childElement.getAttribute('message');
        if(message)
        {
            this.optional.message = message;
        }
        if(expected)
        {
            if(typeof this.required.expected != 'undefined')
            {
                this.required.expected = expected;
            }
        }
        var serializer = new XMLSerializer();
        var temp = serializer.serializeToString(element.getElementsByTagName(this.target).item(0));


        var idx = temp.indexOf('xmlns:tf="TestFire"');
        var finderString = temp.substring(0, idx);
        finderString = finderString + temp.substring(idx + 20);

        this.required[this.target] = finderString;        
        /* @todo it would be great to try to find the target in the DOM, but that is likely to be crazy difficult.
        * Basically re-write watij.
        */
    },

    doToXMLStringAry: function( attributes )
    {
        var ary = new Array();
        var str = "<tf:Assertion ";

        ary.push(str + ">");
        str = "<tf:" + this._cmd;
        if ( attributes )
        {
            str = this.addAttrs(str, attributes);
            str = this.addAttrs(str, {message: this.optional.message});
        }
        ary.push(str + ">");

        if ( this.target && this.required[this.target] )
        {
            ary = ary.concat(this.required[this.target]);
        }
        ary.push("</tf:" + this._cmd + ">");
        ary.push("</tf:Assertion>");
        return ary;
    },

    toXMLStringAry: function( nestedEls )
    {
        if(typeof this.required.expected != 'undefined')
        {
            return this.doToXMLStringAry({expected: this.required.expected});
        }
        else{
            return this.doToXMLStringAry();
        }
    },

    toString : function()
    {
        /* @todo improve this. */
        return this.displayValue; 
    },

    doPopulate: function( parent, targetObject, htmlFinder, finderName )
    {
        try
        {
            this.parent = parent;
            this.htmlFinder = htmlFinder;
            this.targetObject = targetObject;
            if ( this.target )
            {
                if ( this.required )
                {
                    this.required[this.target] =
                        FinderBuilder.build(targetObject, htmlFinder, finderName, this.target, this.args);
                    if ( this.required[this.target] == null )
                    {
                        alert("Aborting Action");
                        return false;
                    }
                }
                if (finderName && typeof(this.required.expected) != 'undefined' )
                {
                    this.required.expected = targetObject[finderName];
                }
            }
            return true;
        }
        catch( ex )
        {
            Firebug.TestFire.util.tf_debug(ex);
        }

    },

    deleteSelf: function()
    {
        this.parent.tasks = this.deleteFromArray(this, this.parent.tasks);
        Firebug.TestFire.refreshAll();
    }



});

/**
 * For the signature assertEquals(boolean, boolean [,message]);
 * @param parent
 */
assertBooleanEquals = function( parent, args )
{
    this.doInit(parent, "Boolean Equals", args);
}

assertBooleanEquals.prototype = domplate(Assertion, {
    _cmd: 'assertBooleanEquals',
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null };
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);
    },
    toXMLStringAry: function()
    {
        return this.doToXMLStringAry({expected: this.required.expected});
    }

});

/**
 * Only used on 'value', but I'm not sure we should even bother. No problems created at the moment by doing so,
 * but if there are the benifits are so low as to be negligable (use Integer instead).
 * For the signature assertEquals(byte, byte [,message]);
 * @param parent
 */
assertByteEquals = function( parent, args )
{
    this.doInit(parent, "Byte Equals", args);
}
assertByteEquals.prototype = domplate(Assertion, {
    _cmd: 'assertByteEquals',
    displayValue: "Byte Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null };
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

/**
 * Only used on 'value', but I'm not sure we should even bother. No problems created at the moment by doing so,
 * but if there are the benifits are so low as to be negligable (use String instead).
 * For the signature assertEquals(byte, byte [,message]);
 * @param parent
 */
assertCharEquals = function( parent, args )
{
    this.doInit(parent, "Char Equals", args);
}
assertCharEquals.prototype = domplate(Assertion, {
    _cmd: 'assertCharEquals',
    displayValue:  "Char Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null };
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});
assertDoubleEquals = function( parent, args )
{
    this.doInit(parent, "Double Equals", args);
}
assertDoubleEquals.prototype = domplate(Assertion, {
    _cmd: 'assertDoubleEquals',
    displayValue:  "Double Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null, delta:0.001 };
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertIntegerEquals = function( parent, args )
{
    this.doInit(parent, "Integer Equals", args);
}
assertIntegerEquals.prototype = domplate(Assertion, {
    _cmd: 'assertIntegerEquals',
    displayValue: "Integer Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);
    }

});

assertObjectEquals = function(parent, args)
{
    this.doInit(parent, "Object Equals", args);
}
assertObjectEquals.prototype = domplate(Assertion, {
    _cmd: 'assertObjectEquals',
    displayValue:  "Object Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertStringEquals = function(parent, args)
{
    this.doInit(parent, "String Equals", args);
}
assertStringEquals.prototype = domplate(Assertion, {
    _cmd: 'assertStringEquals',
    displayValue:  "String Equals",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        var x = this.doPopulate.apply(this, arguments);
        if ( x && finderName )
        {
            this.required.expected = targetObject[finderName];
        }
        return x;
    }

});

assertFalse = function( parent, args )
{
    this.doInit(parent, "False", args);
}
assertFalse.prototype = domplate(Assertion, {
    _cmd: 'assertFalse',
    displayValue:  "False",
    target: "condition",
    init: function()
    {
        this.required = {condition:""};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertTrue = function( parent, args )
{
    this.doInit(parent, "True", args);
}
assertTrue.prototype = domplate(Assertion, {
    _cmd: 'assertTrue',
    displayValue:  "True",
    target: "condition",
    init: function()
    {
        this.required = {condition:""};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertNotNull = function( parent, args )
{
    this.doInit(parent, "Not Null", args);
}
assertNotNull.prototype = domplate(Assertion, {
    _cmd: 'assertNotNull',
    displayValue: "Not Null",
    target: "object",
    init: function()
    {
        this.required = {object: ""};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertNotSame = function( parent, args )
{
    this.doInit(parent, "Not Same", args);
}
assertNotSame.prototype = domplate(Assertion, {
    _cmd: 'assertNotSame',
    displayValue: "Not Same",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

assertNull = function( parent, args )
{
    this.doInit(parent, "Null", args);
}
assertNull.prototype = domplate(Assertion, {
    _cmd: 'assertNull',
    displayValue:  "Null",
    target: "object",
    init: function()
    {
        this.required = {object: ""};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);
    }
});
assertSame = function( parent, args )
{
    this.doInit(parent, "Same", args);
}
assertSame.prototype = domplate(Assertion, {
    _cmd: 'assertSame',
    displayValue:   "Same",
    target: "actual",
    init: function()
    {
        this.required = {expected:null,actual:null};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});

fail = function( parent, args )
{
    this.doInit(parent, "Fail", args);
}
fail.prototype = domplate(Assertion, {
    _cmd: 'fail',
    displayValue:  "Fail",
    init: function()
    {
        this.required = {};
        this.optional = {message:""};
    },
    populate: function( parent, targetObject, htmlFinder, finderName )
    {
        return this.doPopulate.apply(this, arguments);

    }
});